import os

# os.environ['CUDA_VISIBLE_DEVICES']='-1'  #只用cpu
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '1'

import numpy as np
import math
from PIL import Image
from myImage.Helper import MyTimer
from myImage.CImage import CImage

from utils.utils import get_classes
from yolo import YOLO
import tensorflow as tf
import inspect


# confidence = 0.001 ##2022-12-12
confidence = 0.4 ##2023-06-24 提高阈值
nms_iou = 0.5

class Runner:
    model = None

    @staticmethod
    def GetYoloModel(reLoad = False, model_path = None):

        if Runner.model != None and reLoad == False:
            return Runner.model

        # gpus = tf.config.experimental.list_physical_devices(device_type='GPU')
        # for gpu in gpus:
        #     tf.config.experimental.set_memory_growth(gpu, True)

        # confidence = 0.001  ##2022-12-12
        # nms_iou = 0.5
        if model_path is None:
            Runner.model = YOLO(confidence=confidence, nms_iou=nms_iou)
        else:
            Runner.model = YOLO(confidence=confidence, nms_iou=nms_iou,
                                model_path=model_path)
        print('------------load model of YOLO in (GetYoloModel)')

        return Runner.model

    @staticmethod
    def DetectImage(src_image_path, dir_dectect_res, cimage, isLoadSubImages=True,
                    listSubImages=[], bReturnListSubs = True, isSaveBoxResult = False,
                    model_path = None):

        myTimer = MyTimer(showString = False)  ###计时器, 有需要才显示

        # myTimer.printRunSeconds('---gpus(s):')
        rawDetects = []
        try:
            boxes = cimage.boxes  ##子图范围
            columns = cimage.columns

            [_, save_seg_img_dir, fileName] = src_image_path
            [_, fName] = os.path.split(fileName)
            [pureName, _] = os.path.splitext(fName)

            classes_path = '=tobacco/leaf_clasees.txt'
            class_names, _ = get_classes(classes_path)

            # confidence = 0.001
            # nms_iou = 0.5

            # yolo = YOLO(confidence=confidence, nms_iou=nms_iou)
            myTimer.printRunSeconds('---------before yolo 1(s):')
            yolo = Runner.GetYoloModel(model_path=model_path)

            myTimer.printRunSeconds('---------loaded yolo 1(s):')

            bExist = len(listSubImages) == 0
            # if isLoadSubImages == False or bExist == True:
            #     print('Runner:DetectImage()出现方法调用问题，listSubImages=[]')#bug 后面要去掉

            for i in range(len(boxes)):
                fileNo = pureName + '_' + CImage.getString(i, columns)

                if isLoadSubImages == True or bExist == True:##图片从文件读取
                    image_path = os.path.join(save_seg_img_dir, fileNo + '.jpg')

                    image = Image.open(image_path)
                else:##图片由数据提取
                    image = listSubImages[i]

                fileDetectRes = os.path.join(dir_dectect_res, '%s.txt' % fileNo)

                # isSaveFiles = True 就保存检测结果到文件（class, score, left, top, right, bottom)
                out_boxes, out_scores, out_classes = yolo.save_detect_file(image,##调用YOLO检测图片
                                                                           class_names,
                                                                           fileDetectRes,
                                                                           isSaveBoxResult)#isSaveBoxResult =True 保存子图的检测结果

                # if isSaveFiles == False:##2023-04-24 为了方便调试，改为了下面
                if bReturnListSubs == True:
                    rawDetects.append(Runner.GetSubImageDetect(out_boxes, out_scores, out_classes))
                ##isSaveFiles == True时这里不需要保存到rawDetects，已经保存到fileDetectRes中

        except Exception as e:
            print(e, type(e))

        myTimer.printRunSeconds('----ending detect 1(s):')
        print('===len of boxes:%d, rawDetects:%d' % (len(boxes), len(rawDetects)))
        return rawDetects

    @staticmethod
    def GetSubImageDetect(out_boxes, out_scores, out_classes):
        if len(out_boxes) == 0:
            return np.empty((0, 6))

        out_boxes = out_boxes.numpy()
        out_scores = out_scores.numpy().reshape(-1, 1)
        out_classes = out_classes.numpy().reshape(-1, 1)

        ins = [1, 0, 3, 2]
        out_boxes = out_boxes[:, ins]

        return np.hstack((out_classes, out_scores, out_boxes))
